#include "../include/timer_wheel.h"
#include "../include/event_loop.h"
#include <sys/timerfd.h>
#include <unistd.h>
#include <cstring>
#include <stdexcept>

namespace net {

// TimerTask实现
TimerTask::TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb)
    : _id(id), _timeout(delay), _task_cb(cb), _canceled(false) {}

TimerTask::~TimerTask()
{
    // 如果任务未被取消，执行回调函数
    if (!_canceled && _task_cb)
        _task_cb();
    
    // 调用释放回调，从TimerWheel的哈希表中移除任务
    if (_release)
        _release();
}

// TimerWheel实现
TimerWheel::TimerWheel(EventLoop *loop)
    : _capacity(60), _tick(0), _wheel(_capacity), _loop(loop),
      _timerfd(createTimerfd()),
      _timerChannel(new Channel(_loop, _timerfd))
{
    LOG_INFO("TimerWheel created. Capacity: %d, Tick interval: 1s", _capacity);

    // 设置定时器可读事件回调
    _timerChannel->setReadCallback(std::bind(&TimerWheel::onTime, this));
    // 启动读事件监控，开始接收定时触发
    _timerChannel->enableReading();
}

TimerWheel::~TimerWheel()
{
    _timerChannel->disableAll(); // 给Channel移除所有感兴趣的事件
    _timerChannel->remove();     // 把Channel从EventLoop上删除掉
    // 关闭定时器文件描述符
    if (_timerfd >= 0)
        close(_timerfd);

    LOG_INFO("TimerWheel destroyed. Total timers: %d", _timers.size());
}

void TimerWheel::timerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb)
{
    LOG_DEBUG("Adding timer task. ID: %d, Delay: %ds", id, delay);

    // 将任务添加操作放入事件循环队列，确保线程安全
    _loop->runInLoop(std::bind(&TimerWheel::timerAddInLoop, this, id, delay, cb));
}

void TimerWheel::timerRefresh(uint64_t id)
{
    LOG_DEBUG("Refreshing timer task. ID: %d", id);

    // 将任务刷新操作放入事件循环队列，确保线程安全
    _loop->runInLoop(std::bind(&TimerWheel::timerRefreshInLoop, this, id));
}

void TimerWheel::timerCancel(uint64_t id)
{
    LOG_DEBUG("Canceling timer task. ID: %d", id);

    // 将任务取消操作放入事件循环队列，确保线程安全
    _loop->runInLoop(std::bind(&TimerWheel::timerCancelInLoop, this, id));
}

bool TimerWheel::hasTimer(uint64_t id) const
{
    // 检查任务是否存在于哈希表中
    return _timers.find(id) != _timers.end();
}

void TimerWheel::removeTimer(uint64_t id)
{
    // 从哈希表中移除任务ID的映射
    auto it = _timers.find(id);
    if (it != _timers.end()) 
    {
        _timers.erase(it);
    }
}

int TimerWheel::createTimerfd()
{
    // 创建单调时钟的定时器（不受系统时间调整影响）
    int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
    if (timerfd < 0)
    {
        LOG_FATAL("Failed to create timerfd. Errno: %d, Reason: %s", 
            errno, strerror(errno));
        LOG_FLUSH();
    }

    // 设置定时器参数：1秒后首次触发，之后每秒触发一次
    struct itimerspec itime;
    std::memset(&itime, 0, sizeof(itime));
    itime.it_value.tv_sec = 1;     // 首次触发时间
    itime.it_value.tv_nsec = 0;
    itime.it_interval.tv_sec = 1;  // 重复触发间隔
    itime.it_interval.tv_nsec = 0;

    // 设置定时器参数
    if (timerfd_settime(timerfd, 0, &itime, nullptr) < 0)
    {
        LOG_ERROR("Timerfd settime failed! errno: %d", errno);
        close(timerfd);
    }

    LOG_INFO("Timerfd created successfully. FD: %d", timerfd);
    return timerfd;
}

int TimerWheel::readTimefd()
{
    uint64_t times;
    // 读取定时器文件描述符，获取超时次数
    int ret = read(_timerfd, &times, sizeof(times));
    if (ret < 0)
    {
        LOG_ERROR("READ TIMERFD FAILED! errno: %d", errno);
        return 0;
    }

    LOG_DEBUG("Timer fired. Expired times: %d", times);
    return times;
}

void TimerWheel::runTimerTask()
{
    int prevTick = _tick;
    // 时间轮指针向前移动一格（模运算确保在0-59范围内）
    _tick = (_tick + 1) % _capacity;

    LOG_DEBUG("Timer tick advanced. Previous tick: %d, Current tick: %d", prevTick, _tick);
    
    // 获取当前槽位的任务数量
    size_t taskCount = _wheel[_tick].size();
    LOG_TRACE("Executing %d timer tasks at tick %d", taskCount, _tick);

    // 清空当前槽位的任务列表
    // 当shared_ptr被销毁时，若引用计数为0，则会触发TimerTask析构
    _wheel[_tick].clear();
}

void TimerWheel::onTime()
{
    // 读取定时器，获取超时次数（可能因系统负载导致多次超时）
    int times = readTimefd();
    
    // 处理所有超时事件
    for (int i = 0; i < times; i++)
    {
        runTimerTask();
    }
}

void TimerWheel::timerAddInLoop(uint64_t id, uint32_t delay, const TaskFunc &cb)
{
    // 检查延迟时间是否超出时间轮容量
    if (delay >= _capacity)
    {
        LOG_ERROR("DELAY EXCEEDS TIMERWHEEL CAPACITY! delay: %d, capacity: %d", delay, _capacity);
        return;
    }

    LOG_DEBUG("Adding timer task in loop. ID: %d, Delay: %d, Slot: %d", 
        id, delay, (_tick + delay) % _capacity);

    // 创建新的任务对象
    PtrTask pt = std::make_shared<TimerTask>(id, delay, cb);
    
    // 设置释放回调，当任务被执行或取消时，从哈希表中移除
    pt->setRelease(std::bind(&TimerWheel::removeTimer, this, id));
    
    // 计算任务应该放入的槽位：当前位置 + 延迟时间
    int pos = (_tick + delay) % _capacity;
    
    // 将任务添加到对应槽位
    _wheel[pos].push_back(pt);
    
    // 同时将任务添加到哈希表，便于快速查找和取消
    _timers[id] = pt;   // 从 PtrTask 隐式转换为 WeakTask
}

void TimerWheel::timerRefreshInLoop(uint64_t id)
{
    // 在哈希表中查找任务
    auto it = _timers.find(id);
    if (it == _timers.end())
    {
        LOG_WARN("Timer task not found when refreshing. ID: %d", id);
        return;
    }

    // 通过weak_ptr获取shared_ptr（如果对象还存在）
    PtrTask pt = it->second.lock();
    if (!pt)
        return;

    // 获取原始延迟时间
    int delay = pt->delayTime();
    
    // 重新计算槽位并添加任务（不改变延迟时间）
    int pos = (_tick + delay) % _capacity;
    _wheel[pos].push_back(pt);
    // 这里不需要删除之前的，因为这里采用的是析构时自动调用。
    // 由于这里的引用计数必定大于等于2，因此前面的不会调用回调函数

    LOG_DEBUG("Refreshing timer task in loop. ID: %d, New Slot: %d", id, pos);
}

void TimerWheel::timerCancelInLoop(uint64_t id)
{
    // 在哈希表中查找任务
    auto it = _timers.find(id);
    if (it == _timers.end())
    {
        LOG_WARN("Timer task not found when canceling. ID: %d", id);
        return;
    }

    LOG_INFO("Canceling timer task in loop. ID: %d", id);

    // 通过weak_ptr获取shared_ptr（如果对象还存在）
    PtrTask pt = it->second.lock();
    if (pt)
        // 标记任务为已取消
        pt->cancel();
    else
        LOG_DEBUG("Timer task already expired, cannot cancel!");
}

} // namespace net